package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.pojo.ImportStatusPojo;
import com.xbongbong.paas.pojo.dto.ImportPerformanceDTO;
import com.xbongbong.paas.pojo.dto.PerformanceDownloadDTO;
import com.xbongbong.paas.pojo.imports.ErrorExcelPerformanceDataPojo;
import com.xbongbong.paas.pojo.imports.ErrorExcelPerformancePojo;
import com.xbongbong.paas.pojo.vo.ExcelTemplateVO;
import com.xbongbong.paas.pojo.vo.ImportPerformanceVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisConstant;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.service.ExcelOperatorService;
import com.xbongbong.paas.service.HandleImportService;
import com.xbongbong.paas.service.PerformanceImportService;
import com.xbongbong.paas.service.PerformanceService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.thread.TransmittableThreadLocalUtil;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.paas.util.ExcelUtil;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.constant.RegExConstant;
import com.xbongbong.pro.domain.entity.ChartEntity;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.TimeTypeEnum;
import com.xbongbong.pro.enums.errorcodes.ImportErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.performance.pojo.PerformancePojo;
import com.xbongbong.pro.performanceset.pojo.PerformanceSetExplainPojo;
import com.xbongbong.pro.service.toolbox.statistic.help.FiscalYearHelp;
import com.xbongbong.pro.service.toolbox.statistic.help.PerformanceHelp;
import com.xbongbong.pro.statistic.enums.SystemCodeEnum;
import com.xbongbong.pro.statistic.model.ChartCustomModel;
import com.xbongbong.pro.statistic.model.ChartModel;
import com.xbongbong.pro.statistic.pojo.FiscalYearTimePojo;
import com.xbongbong.pro.statistic.result.pojo.TimeListPojo;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.constant.export.ImportConstant;
import com.xbongbong.saas.domain.entity.PerformanceEntity;
import com.xbongbong.saas.enums.AssessTypeEnum;
import com.xbongbong.saas.enums.MinCycleEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.PerformanceTypeEnum;
import com.xbongbong.saas.model.PerformanceModel;
import com.xbongbong.saas.toolbox.help.BasicHelper;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.enums.CompanyStructTypeEnum;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserModel;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * 业绩目标导入导出Service层
 *
 * @author wufeng
 * @date 2018/9/21 14:47
 */
@Service("performanceImportService")
public class PerformanceImportServiceImpl implements PerformanceImportService {

    private static final Logger LOG = LoggerFactory.getLogger(PerformanceImportServiceImpl.class);

    @Resource
    private ExcelOperatorService excelOperatorService;
    @Resource
    private HandleImportService handleImportService;
    @Resource
    private ChartModel chartModel;
    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private UserModel userModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private PerformanceModel performanceModel;
    @Resource
    private PerformanceService performanceService;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private PerformanceHelp performanceHelp;
    @Resource
    private ChartCustomModel chartCustomModel;
    @Resource
    private MongoLogHelp mongoLogHelp;

    @Override
    public ExcelTemplateVO getPerformanceTemplate(PerformanceDownloadDTO performanceDownloadDTO) throws XbbException {
        ExcelTemplateVO excelTemplateVO = new ExcelTemplateVO();
        try {
            String corpid = performanceDownloadDTO.getCorpid();
            String type = performanceDownloadDTO.getType();
            Long setId = performanceDownloadDTO.getSetId();
            Integer year = performanceDownloadDTO.getYear();
            PerformanceTypeEnum performanceTypeEnum = PerformanceTypeEnum.getByType(type);
            //获取图表
            ChartEntity setEntity = performanceHelp.getSetEntity(performanceDownloadDTO.getStatisticsType(),corpid,setId);
            if (Objects.isNull(setEntity.getExplains())) {
                PerformanceSetExplainPojo explainPojo = new PerformanceSetExplainPojo();
                setEntity.setExplains(JSON.parseObject(JSON.toJSONString(explainPojo)));
            }
            PerformanceSetExplainPojo performanceSetExplainPojo = setEntity.getExplains().toJavaObject(PerformanceSetExplainPojo.class);
            if (Objects.equals(performanceSetExplainPojo.getAssessType(), AssessTypeEnum.FIXED.getCode())) {
                // 固定数值类型，无需导入
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, I18nStringConstant.IMPORT_NOT_NEED);
            }
            // 从配置表获取财年配置
            int startMonth = companyConfigModel.getFiscalStartMonth(corpid);
            String labelFiscalYear = FiscalYearHelp.getLableFiscalYear(startMonth, "");

            String titleRowContent = I18nMessageUtil.getMessage(ImportConstant.PERFORMANCE_IMPORT_TITLE_WARNING);
            titleRowContent = String.format(titleRowContent, setEntity.getName(), labelFiscalYear);

            List<String> colTitle = new ArrayList<>();
            //置入第一列标题名
            colTitle.add(0, performanceTypeEnum.getTitleName());
            Map<String, Object> tipMap = dealWithPerformanceColumnTitle(year, startMonth, performanceSetExplainPojo, colTitle);
            tipMap.put("title", titleRowContent);
            List<Map<String, Object>> titleList = new ArrayList<>();
            titleList.add(tipMap);
            List<List<Map<String, Object>>> moreTitleList = new ArrayList<>();
            moreTitleList.add(titleList);

            String[] colSecondTitle = new String[colTitle.size()];
            //对每个月下面的几个目标标题填值
            for (int i = 0; i < colTitle.size(); i++) {
                colSecondTitle[i] = colTitle.get(i);
            }
            Workbook workbook = excelOperatorService.createEmptyExcel4MoreTitle(10, performanceTypeEnum.getExcelName(), colSecondTitle, moreTitleList);
            excelTemplateVO.setWorkbook(workbook);
            excelTemplateVO.setName(performanceTypeEnum.getExcelName() + ImportConstant.EXCEL_SUFFIX);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("生成业绩目标导入模板错误", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, e.getMessage());
        }
        return excelTemplateVO;
    }

    @Override
    public Workbook getErrorPerformanceTemplate(Integer year, Integer startMonth, ChartEntity setEntity) throws XbbException {
        try {
            String name = setEntity.getName();
            String rowTitle = year + I18nMessageUtil.getMessage(I18nStringConstant.FISCAL_YEAR) + "，“" + name + I18nMessageUtil.getMessage(I18nStringConstant.IMPORT_INDICATOR);

            List<Map<String, Object>> titleList = new ArrayList<>();
            List<String> colTitle = new ArrayList<>();
            colTitle.add(I18nMessageUtil.getMessage(CommonConstant.ERROR));
            colTitle.add(I18nMessageUtil.getMessage(CommonConstant.NAME));
            PerformanceSetExplainPojo performanceSetExplainPojo = setEntity.getExplains().toJavaObject(PerformanceSetExplainPojo.class);
            Map<String, Object> tipMap = this.dealWithPerformanceColumnTitle(year, startMonth, performanceSetExplainPojo, colTitle);
            tipMap.put("title", rowTitle);
            titleList.add(tipMap);
            List<List<Map<String, Object>>> moreTitleList = new ArrayList<>();
            moreTitleList.add(titleList);

            String[] colSecondTitle = new String[colTitle.size()];
            for (int i = 0; i < colTitle.size(); i++) {
                colSecondTitle[i] = colTitle.get(i);
            }
            return excelOperatorService.createEmptyExcel4MoreTitle(10, I18nMessageUtil.getMessage(CommonConstant.ERROR_INFO), colSecondTitle, moreTitleList);
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, e.getMessage());
        }
    }

    @Override
    public Workbook performanceErrorDownLoad(BaseDTO baseDTO) throws XbbException {
        String hashKey = baseDTO.getCorpid() + "_" + baseDTO.getUserId() + "_" + "performanceImport";
        String value = paasRedisHelper.getValue(RedisPrefixConstant.IMPORT_PERFORMANCE_ERROR_EXCEL_KEY, hashKey);
        ErrorExcelPerformancePojo errorExcelPerformancePojo = JSON.parseObject(value, ErrorExcelPerformancePojo.class);
        Workbook errorExcel = getErrorPerformanceTemplate(errorExcelPerformancePojo.getYear(), errorExcelPerformancePojo.getStartMonth(), errorExcelPerformancePojo.getSetEntity());
        List<ErrorExcelPerformanceDataPojo> errorList = errorExcelPerformancePojo.getErrorList();
        for (ErrorExcelPerformanceDataPojo errorDataPojo : errorList) {
            ExcelUtil.addError(errorExcel, errorDataPojo.getMsg(), errorDataPojo.getVal());
        }
        return errorExcel;
    }

    @Override
    public ImportPerformanceVO importPerformanceData(ImportPerformanceDTO importPerformanceDTO) throws XbbException {
        // 读取导入任务状态缓存
        String hashKey = importPerformanceDTO.getCorpid() + "_" + importPerformanceDTO.getUserId();
        ImportStatusPojo statusPojo = JsonHelperUtil.parseObject(paasRedisHelper.getValue(RedisPrefixConstant.IMPORT_STATUS_KEY, hashKey), ImportStatusPojo.class);
        if (statusPojo != null && !statusPojo.getFinish()) {
            // 上次导入任务未结束
            throw new XbbException(ImportErrorCodeEnum.API_ERROR_235001);
        }
        // 上次导入状态缓存清除
        String hashErrorKey = hashKey + "_" + "performanceImport";
        paasRedisHelper.removeValue(RedisPrefixConstant.IMPORT_STATUS_KEY, hashKey);
        paasRedisHelper.removeValue(RedisPrefixConstant.IMPORT_PERFORMANCE_ERROR_EXCEL_KEY, hashErrorKey);

        ImportPerformanceVO importPerformanceVO;
        try {
            UserEntity userEntity = new UserEntity();
            BeanUtil.copyProperties(importPerformanceDTO.getLoginUser(), userEntity);
            String corpid = importPerformanceDTO.getCorpid();
            String type = importPerformanceDTO.getType();
            Integer year = importPerformanceDTO.getYear();
            Long setId = importPerformanceDTO.getSetId();
            int objectiveType = PerformanceTypeEnum.getByType(type).getObjectiveType();
            //获取图表
            ChartEntity setEntity = performanceHelp.getSetEntity(importPerformanceDTO.getStatisticsType(),corpid,setId);
            if (Objects.isNull(setEntity.getExplains())) {
                PerformanceSetExplainPojo explainPojo = new PerformanceSetExplainPojo();
                setEntity.setExplains(JSON.parseObject(JSON.toJSONString(explainPojo)));
            }
            PerformanceSetExplainPojo performanceSetExplainPojo = setEntity.getExplains().toJavaObject(PerformanceSetExplainPojo.class);
            if (Objects.equals(performanceSetExplainPojo.getAssessType(), AssessTypeEnum.FIXED.getCode())) {
                // 固定数值类型，无需导入
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, I18nStringConstant.IMPORT_NOT_NEED);
            }

            InputStream fileInputStream = importPerformanceDTO.getFile().getInputStream();
            Workbook workBook = WorkbookFactory.create(fileInputStream);
            String[][] excelArray = handleImportService.getExcelValue(workBook, 1);
            // Excel总行数 包含标题（第一行是大标题，第二行是小标题）等的行数
            int rowNum = excelArray.length;
            // 默认从第3行开始读数据：第一行是大标题，第二行是小标题(时间维度)
            int firstRow = 2;
            if (rowNum <= firstRow) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, I18nStringConstant.MISSED_INDICATOR_DATA);
            }
            if (rowNum > ImportConstant.MAX_EXCEL_IMPORT_COUNT + firstRow) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, I18nStringConstant.IMPORT_EXCEEDS);
            }
            // 财年起始月
            int startMonth = companyConfigModel.getFiscalStartMonth(corpid);
            // 导入数据
            importPerformanceVO = importData(importPerformanceDTO, excelArray, firstRow, rowNum, userEntity, setEntity, objectiveType, year, startMonth);
            if (importPerformanceVO.getHasError()) {
                ErrorExcelPerformancePojo errorExcelPerformancePojo = new ErrorExcelPerformancePojo(importPerformanceVO.getErrorList(), year, startMonth, setEntity);
                paasRedisHelper.setValue(RedisPrefixConstant.IMPORT_PERFORMANCE_ERROR_EXCEL_KEY, hashErrorKey, errorExcelPerformancePojo, RedisConstant.LONG_DURATION);
            }
            if(importPerformanceVO.getSuccessNum() > 0){
                //记录日志，不记录详情
                String name = PerformanceTypeEnum.PERFORMANCE_USER.getType().equals(importPerformanceDTO.getType()) ? CompanyStructTypeEnum.USER.getName() : CompanyStructTypeEnum.DEPARTMENT.getName();
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_IMPORT_PERFORMANCE_FROM_EXCEL),userEntity.getName(),setEntity.getName(),importPerformanceVO.getSuccessNum(),name);
                mongoLogHelp.buildLog(corpid,userEntity.getUserId(),userEntity.getName(), OperateModuleTypeEnum.PerformanceObject,
                        OperateTypeEnum.IMPORT,String.valueOf(setEntity.getId()), StringConstant.PERFORMANCE_IMPORT,
                        memo,importPerformanceDTO.getHttpHeader());
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("导入信息异常，中途报错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, e.getMessage());
        }
        return importPerformanceVO;
    }

    /**
     * 处理excel（导入模版、错误模版）标题
     *
     * @param year                      年
     * @param startMonth                财年起始月
     * @param performanceSetExplainPojo 指标实体
     * @param colTitle                  横坐标标题
     * @return tipMap：columnCount--合并列数
     * @version performance-v1.0.1
     * @author chuanpeng.zhang
     * @date 2018年11月21日 上午9:37:42
     * @since performance-v1.0.1
     */
    private Map<String, Object> dealWithPerformanceColumnTitle(Integer year, int startMonth, PerformanceSetExplainPojo performanceSetExplainPojo, List<String> colTitle) {
        Map<String, Object> tipMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Integer minCycle = performanceSetExplainPojo.getMinCycle();
        if (MinCycleEnum.WEEK.getCode() == minCycle) {
            List<String> weekPeriodList = FiscalYearHelp.getWeeks4Year(year, startMonth);
            List<String> titleList = new ArrayList<>();
            for (int i = 0; i < weekPeriodList.size(); i++) {
                String week = weekPeriodList.get(i);
                String weekPeriod = I18nMessageUtil.getMessage(I18nStringConstant.FISCAL_YEAR_FIRST) + (i + 1) + I18nMessageUtil.getMessage(CommonConstant.WEEK) + "(" + week + ")";
                titleList.add(weekPeriod);
            }
            colTitle.addAll(titleList);
            tipMap.put("columnCount", 1 + weekPeriodList.size());
        } else {
            // 横坐标--月份：业绩目标要获取整年的，因此timeType为年类型即可
            List<String> dateList = I18nStringConstant.ABSCISSA_MONTH;
            colTitle.addAll(dateList);
            tipMap.put("columnCount", 13);
        }
        return tipMap;
    }

    /**
     * 处理exce目标导入数据
     *
     * @param importPerformanceDTO 入参
     * @param excelArray           excel数据
     * @param firstRow             第一个有数据的行
     * @param rowNum               总行数
     * @param userEntity           登录员工
     * @param setEntity            指标实体
     * @param objectiveType        业绩类型：1员工的业绩 2部门的业绩
     * @param year                 财年年份
     * @param startMonth           财年起始月
     * @return 是否有错误
     * @throws XbbException XbbException
     * @version performance-v1.0
     * @author cp.zhang
     * @date 2018年8月22日 下午7:01:49
     * @since performance-v1.0
     */
    private ImportPerformanceVO importData(ImportPerformanceDTO importPerformanceDTO, String[][] excelArray, int firstRow, int rowNum, UserEntity userEntity,
                                           ChartEntity setEntity, Integer objectiveType, Integer year, Integer startMonth) throws XbbException {
        PerformanceSetExplainPojo performanceSetExplainPojo = setEntity.getExplains().toJavaObject(PerformanceSetExplainPojo.class);

        String userId = userEntity.getUserId();
        String corpid = userEntity.getCorpid();
        boolean hasError = false;
        Long now = DateTimeUtil.getInt();
        String systemCode = setEntity.getSystemCode();
        SystemCodeEnum systemCodeEnum = SystemCodeEnum.getByCode(systemCode);
        TransmittableThreadLocalUtil.setValue(SaasMarkEnum.SAAS.getCode(), systemCodeEnum.getXbbRefTypeEnum().getCode(), null, importPerformanceDTO.getDistributorMark());
        Integer dataPermission = userModel.getDataPermission(userEntity);
        // 下属员工ids
        List<String> userIdIn = new ArrayList<>();
        // 主管的部门ids
        List<Long> depIdIn = new ArrayList<>();

        // 员工姓名--员工userId
        Map<String, String> userIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (objectiveType == CompanyStructTypeEnum.USER.getCode()) {
            // 先获取员工
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("del", 0);
            param.put("columns", "user_id, name");
            List<UserEntity> userList = (List<UserEntity>) BasicHelper.findEntitysByImitatePage(param, userModel);
            for (UserEntity user : userList) {
                userIdMap.put(user.getName(), user.getUserId());
            }
            if (dataPermission != 5) {
                userIdIn.addAll(userModel.getSubIdListByDataPermission(dataPermission, userId, corpid, BasicConstant.ONE, false));
            }
        } else {
            if (dataPermission != 5) {
                Set<Long> subDepIdSet = new HashSet<>(userModel.getUserManageDeptIdList(userEntity, true));
                // 获取主管的部门的子部门
                // depIdIn.addAll(departmentModel.getRecursionDepFromJedis2DepIds(corpid, subDepIdSet));
                depIdIn.addAll(departmentModel.getSubDepIdList(corpid, subDepIdSet));
            }
        }
        // 设置查询业绩目标表的pojo，但是userId/departmentId需要在下面循环内置入
        PerformancePojo performancePojo = new PerformancePojo();
        performancePojo.setYear(year);
        performancePojo.setSetId(setEntity.getId());
        performancePojo.setCompanyStructType(objectiveType);
        performancePojo.setStatisticsType(importPerformanceDTO.getStatisticsType());
        /*
         * 根据不同的最小考核周期，生成不同的索引
         * 当最小考核周期是周时：获取12个月份的开始结束时间
         */
        Integer minCycle = performanceSetExplainPojo.getMinCycle();
        MinCycleEnum minCycleEnum = MinCycleEnum.getByCode(minCycle);
        if (Objects.isNull(minCycleEnum)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, I18nStringConstant.ASSESSMENT_CYCLE_NOT_EMPTY);
        }
        List<String> indexList = new ArrayList<>();
        int fiscalStartTime = 0;
        List<Integer> startTimeList = new ArrayList<>();
        List<Integer> endTimeList = new ArrayList<>();
        if (MinCycleEnum.WEEK == minCycleEnum) {
            indexList = FiscalYearHelp.getWeekIndexs4Year(year, startMonth);
            // 获取财年起始，获取各个月份的起止时间戳
            fiscalStartTime = FiscalYearHelp.getFiscalYearStartInt(year, startMonth);
            FiscalYearTimePojo fiscalYearTimePojo = new FiscalYearTimePojo();
            fiscalYearTimePojo.setYear(year);
            TimeListPojo timeRet = FiscalYearHelp.getTimeList(fiscalYearTimePojo, TimeTypeEnum.YEAR.getCode(), 0, startMonth);
            startTimeList = timeRet.getStartTimeList();
            endTimeList = timeRet.getEndTimeList();
        } else {
            for (int i = 1; i <= 12; i++) {
                indexList.add("m" + i);
            }
        }

        // 数据有多少行
        int dataRowNum = rowNum - firstRow;
        ImportStatusPojo importStatusPojo = new ImportStatusPojo();
        importStatusPojo.setTotalNum(dataRowNum);
        String hashKey = importPerformanceDTO.getCorpid() + "_" + importPerformanceDTO.getUserId();
        // 当前已经处理到第几行数据
        int nowRowNum = 0;
        List<ErrorExcelPerformanceDataPojo> errorList = new ArrayList<>();
        /*
         * 遍历行，从第firstRow+1行开始导入
         */
        for (int i = firstRow; i < rowNum; i++) {
            nowRowNum++;
            // 每隔5条/数据导完时，刷新一次当前导入状态
            if (nowRowNum == 1 || nowRowNum % 5 == 0 || nowRowNum >= dataRowNum) {
                paasRedisHelper.setValue(RedisPrefixConstant.IMPORT_STATUS_KEY, hashKey, importStatusPojo, RedisConstant.TINY_DURATION);
            }

            //用来装员工目标实体，共计每个员工1个实体
            JSONArray objectArray = new JSONArray();
            // 读取左上端单元格
            // 第i+1行
            String[] val = excelArray[i];
            // 行没数据跳过
            boolean isEmpty = true;
            // 是否是0或者正数
            boolean legalData = true;
            /*
             * key为“m1、m2、m3...”或者“w1、w2、w3...”
             * value为目标值
             */
            JSONObject perObject = new JSONObject();
            for (int j = 0; j < indexList.size(); j++) {
                // 第一列是员工姓名/部门名称，因此要从j+1列开始获取数据
                String targetStr = StringUtil.getArrayVal(val, j + 1);
                if (StringUtil.isEmpty(targetStr)) {
                    continue;
                }
                // 判断数据是否合法
                if (!targetStr.matches(RegExConstant.PERFORMANCE_TARGET)) {
                    legalData = false;
                    break;
                }
                Double target = StringUtil.toDouble(targetStr, -1D);
                // 判断小数位数是否大于等于3，若为真，则四舍五入转换成两位小数
                if (targetStr.matches(RegExConstant.PERFORMANCE_TARGET_FORMAT)) {
                    target = StringUtil.toDouble(StringUtil.formatDouble(target, "###0.00"), -1D);
                }
                String key = indexList.get(j);
                perObject.put(key, target);
                if (isEmpty && target >= 0) {
                    // 不为空，空标记flag置为false
                    isEmpty = false;
                }
            }
            if (!legalData) {
                errorList.add(new ErrorExcelPerformanceDataPojo(I18nMessageUtil.getMessage(I18nStringConstant.ILLEGAL_DATA), val));
                hasError = true;
                continue;
            }
            // 行没数据跳过逻辑结束
            if (isEmpty) {
                errorList.add(new ErrorExcelPerformanceDataPojo(I18nMessageUtil.getMessage(I18nStringConstant.NO_TARGET_VALUE_ENTERED), val));
                hasError = true;
                continue;
            }
            // 每行第一格为员工姓名/部门名称
            String name = StringUtil.getArrayVal(val, 0);
            if (objectiveType == CompanyStructTypeEnum.USER.getCode()) {
                if (StringUtil.isEmpty(name)) {
                    errorList.add(new ErrorExcelPerformanceDataPojo(I18nMessageUtil.getMessage(I18nStringConstant.MISSED_EMPLOYEE_NAME), val));
                    hasError = true;
                    continue;
                }
                String importUserId = userIdMap.get(name);
                if (StringUtil.isEmpty(importUserId)) {
                    errorList.add(new ErrorExcelPerformanceDataPojo(I18nMessageUtil.getMessage(CommonConstant.EMPLOYEE) + "“" + name + "”" + I18nMessageUtil.getMessage(I18nStringConstant.NOT_EXIST_OR_DELETED), val));
                    hasError = true;
                    continue;
                }
                if (dataPermission != 5 && !userIdIn.contains(importUserId)) {
                    errorList.add(new ErrorExcelPerformanceDataPojo(I18nMessageUtil.getMessage(CommonConstant.EMPLOYEE) + "“" + name + "”" + I18nMessageUtil.getMessage(I18nStringConstant.NOT_YOUR_SUBORDINATE), val));
                    hasError = true;
                    continue;
                }
                //                if (!performanceSetModel.checkViewPerformanceSet(corpid, importUserId, setEntity)) {
                //                    ExcelUtil.addError(errorExcel, "员工“" + name + "”不在该指标考核范围内", val);
                //                    hasError = true;
                //                    continue;
                //                }
                // 获取到目标对象 设置pojo的员工id
                performancePojo.setUserId(importUserId);
            } else {
                if (StringUtil.isEmpty(name)) {
                    errorList.add(new ErrorExcelPerformanceDataPojo(I18nMessageUtil.getMessage(I18nStringConstant.MISSED_DEPARTMENT_NAME), val));
                    hasError = true;
                    continue;
                }
                Map<String, Object> depMap = departmentModel.getDepIdByNames(name, corpid);
                DepartmentEntity departmentEntity = (DepartmentEntity) depMap.get("retEntity");
                if (departmentEntity == null) {
                    errorList.add(new ErrorExcelPerformanceDataPojo(I18nMessageUtil.getMessage(CommonConstant.DEPARTMENT) + "“" + name + "”" + I18nMessageUtil.getMessage(I18nStringConstant.NOT_EXIST_OR_DELETED), val));
                    hasError = true;
                    continue;
                }
                Long departmentId = departmentEntity.getId();
                if (dataPermission != 5 && !depIdIn.contains(departmentId)) {
                    errorList.add(new ErrorExcelPerformanceDataPojo(I18nMessageUtil.getMessage(CommonConstant.DEPARTMENT) + "“" + name + "”" + I18nMessageUtil.getMessage(I18nStringConstant.NOT_YOUR_DEPARTMENT), val));
                    hasError = true;
                    continue;
                }
                //                if (!performanceSetModel.checkViewPerformanceSet(corpid, departmentId, setEntity)) {
                //                    ExcelUtil.addError(errorExcel, "部门“" + name + "”不在该指标考核范围内", val);
                //                    hasError = true;
                //                    continue;
                //                }
                // 获取到目标对象 设置pojo的员工id
                performancePojo.setDepartmentId(departmentId);
            }
            // 处理目标
            PerformanceEntity performanceEntity = performanceModel.getPerformanceEntity(corpid, performancePojo);
            if (performanceEntity.getId() == null) {
                // 新增目标
                performanceEntity.setAddTime(now);
            }
            JSONObject target = getTarget(minCycleEnum, performanceEntity.getTarget(), perObject, fiscalStartTime, startTimeList, endTimeList);
            performanceEntity.setDel(0);
            performanceEntity.setTarget(target);
            performanceEntity.setUpdateTime(now);
            performanceEntity.setStatisticsType(importPerformanceDTO.getStatisticsType());
            try {
                performanceModel.save(performanceEntity);
                String month = JSONObject.toJSONString(performanceEntity);
                JSONObject monthObject = JSONObject.parseObject(month);
                objectArray.add(monthObject);
            } catch (Exception e) {
                errorList.add(new ErrorExcelPerformanceDataPojo(I18nMessageUtil.getMessage(I18nStringConstant.PERFORMANCE_SAVE_ERROR), val));
                hasError = true;
                continue;
            }
            int successNum = importStatusPojo.getSuccessNum();
            importStatusPojo.setSuccessNum(++successNum);
        }

        // 导入状态缓存
        importStatusPojo.setFinish(true);
        importStatusPojo.setErrorNum(errorList.size());
        paasRedisHelper.setValue(RedisPrefixConstant.IMPORT_STATUS_KEY, hashKey, importStatusPojo, RedisConstant.SHORT_DURATION);

        ImportPerformanceVO importPerformanceVO = new ImportPerformanceVO();
        importPerformanceVO.setSuccessNum(importStatusPojo.getSuccessNum());
        importPerformanceVO.setHasError(hasError);
        importPerformanceVO.setErrorList(errorList);
        importPerformanceVO.setChartEntity(setEntity);
        return importPerformanceVO;
    }

    /**
     * 处理目标
     * 月维度的：求和月目标以得到相应的年、半年、季度目标
     * 周维度：（1）求和每月的各个周，得到各个月目标；（2）求和月目标以得到相应的年、半年、季度目标
     *
     * @param minCycleEnum    最小考核周期
     * @param oldTargetObject 旧的指标值（编辑时代表之前旧的，如果是新建的，也传前端传入的指标对象即可）
     * @param perObject       excel一行上输入的所有目标（各个时间段）
     * @param fiscalStartTime 财年起始时间戳
     * @param startTimeList   各个月开始时间列表
     * @param endTimeList     各个月结束时间列表
     * @return 处理过后的目标对象
     * @version performance-v1.0
     * @author cp.zhang
     * 创建时间：2018年8月22日 下午4:59:44
     * 修改时间：
     * @since performance-v1.0
     */
    private JSONObject getTarget(MinCycleEnum minCycleEnum, JSONObject oldTargetObject, JSONObject perObject, Integer fiscalStartTime, List<Integer> startTimeList, List<Integer> endTimeList) throws XbbException {
        JSONObject targetObject = new JSONObject();
        switch (minCycleEnum) {
            case MONTH:
                //最小考核周期为月，处理年、半年、季度（没设置则汇总月）
                targetObject.put(TimeTypeEnum.MONTH.getAlias(), perObject);
                oldTargetObject = performanceService.dealWithTargetObject(oldTargetObject, targetObject);
                break;
            case WEEK:
                //最小考核周期为周，则先汇总出所有对应的月目标，然后再汇总处理年、半年、季度（没设置则汇总月）
                JSONObject monthObject = new JSONObject();
                for (int i = 0; i < startTimeList.size(); i++) {
                    Integer monthStart = startTimeList.get(i);
                    Integer monthEnd = endTimeList.get(i);
                    //得到属于当月的所有周索引
                    List<String> weekIndexsList = FiscalYearHelp.getWeekIndex4Month(fiscalStartTime, monthStart, monthEnd);
                    Double monthTotal = 0D;
                    for (String weekKey : weekIndexsList) {
                        Double target = perObject.getDouble(weekKey);
                        if (target != null && target > 0) {
                            monthTotal += target;
                        }
                    }
                    monthObject.put("m" + (i + 1), monthTotal);
                }
                targetObject.put(TimeTypeEnum.MONTH.getAlias(), monthObject);
                oldTargetObject = performanceService.dealWithTargetObject(oldTargetObject, targetObject);
                oldTargetObject.put(TimeTypeEnum.WEEK.getAlias(), perObject);
                break;
            default:
                break;
        }
        return oldTargetObject;
    }
}
